/*
 *  LLFileUtils.cpp
 *  LID Library
 *
 *  Created by Alexander Trutchenko on 09/11/11.
 *  Copyright 2011 League of Independent Developers. All rights reserved.
 *
 */

#include "lid_lib/src/file_managment/LLFileUtils.h"

#include "lid_lib/src/service/LLLog.h"

#include "windows.h"




using namespace std;

namespace lidlib {

void _CheckPath()
{
	if (LLFileUtils::getResourcePath().empty())
	{
		char pszResourcePath[MAX_PATH];
		WCHAR  wszPath[MAX_PATH];
		int nNum = WideCharToMultiByte(CP_ACP, 0, wszPath, 
			GetCurrentDirectoryW(sizeof(wszPath), wszPath), 
			pszResourcePath, MAX_PATH, NULL, NULL);
        pszResourcePath[nNum] = '\\';
		pszResourcePath[nNum + 1] = 0;
		LLLOG(pszResourcePath);
		LLFileUtils::setResourcePath(pszResourcePath);
	}
}

/////////////////////////////////////////////////////
//
/** LLFileUtils 
* 
*/
/////////////////////////////////////////////////////

std::string LLFileUtils::fullPathFromRelativePath(const std::string& relativePath)
{
	_CheckPath();

    std::string ret;
	if ((relativePath.size() > 1 && relativePath[1] == ':'))
    {
        // path start with "x:", is absolute path
        ret = relativePath;
    }
    else if (!relativePath.empty() && ('/' == relativePath[0] || '\\' == relativePath[0]))
    {
        // path start with '/' or '\', is absolute path without driver name
		char szDriver[3] = {LLFileUtils::getResourcePath()[0], LLFileUtils::getResourcePath()[1], 0};
        ret = szDriver;
        ret += relativePath;
    }
    else
    {
        ret = LLFileUtils::getResourcePath();
		ret += "/";
        ret += relativePath;
    }

	return ret;
}

std::string LLFileUtils::fullPathFromRelativeFile(const std::string& filename, const std::string& relativeFile)
{
	_CheckPath();
	std::string fullFile = fullPathFromRelativePath(relativeFile);
	std::string ret = fullFile.substr(0, fullFile.find_last_of("/\\") + 1);
	ret += filename;
	return ret;
}

unsigned char* LLFileUtils::getFileData(const std::string& fileName, unsigned long * pSize)
{
    // read the file from hardware
    FILE *fp = fopen(fileName.c_str(), "rb");
    if (fp == NULL)
		return NULL;

    fseek(fp,0,SEEK_END);
    *pSize = ftell(fp);

    fseek(fp,0,SEEK_SET);
    unsigned char* pBuffer = new unsigned char[*pSize];
    *pSize = fread(pBuffer,sizeof(unsigned char), *pSize,fp);
    fclose(fp);

    return pBuffer;
}

string LLFileUtils::getWriteablePath()
{
	// return the path that the exe file saved in

	char full_path[_MAX_PATH + 1];
	::GetModuleFileNameA(NULL, full_path, _MAX_PATH + 1);

	string ret((char*)full_path);

	// remove xxx.exe
	ret =  ret.substr(0, ret.rfind("\\") + 1);

	return ret;
}

bool LLFileUtils::isFileExists(const std::string& fileName)
{
	FILE *fp = fopen(fileName.c_str(), "rb");
	if(fp == NULL)
		return false;
	fclose(fp);
	return true;
}

std::vector<std::string> LLFileUtils::getFileList(const std::string& fullDirectoryPath)
{
	std::vector<std::string> result;

	WIN32_FIND_DATAA FindFileData; 
	HANDLE hFind = INVALID_HANDLE_VALUE; 

	std::string fingStr = fullDirectoryPath;
	fingStr += "/*";
	
	hFind = FindFirstFileA(fingStr.c_str(), &FindFileData);
 
    if (hFind == INVALID_HANDLE_VALUE)
		return result;

	if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
		result.push_back(FindFileData.cFileName);
 
    while(FindNextFileA(hFind, &FindFileData) != 0)
    {
		if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
			result.push_back(FindFileData.cFileName);
    }
 
	FindClose(hFind);

	return result;
}

std::vector<std::string> LLFileUtils::getDirectoryList(const std::string& fullDirectoryPath)
{
	std::vector<std::string> result;

	WIN32_FIND_DATAA FindFileData; 
	HANDLE hFind = INVALID_HANDLE_VALUE; 

	std::string fingStr = fullDirectoryPath;
	fingStr += "/*";
	
	hFind = FindFirstFileA(fingStr.c_str(), &FindFileData);
 
    if (hFind == INVALID_HANDLE_VALUE)
		return result;

	if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
		(strcmp(FindFileData.cFileName, ".") != 0) &&
		(strcmp(FindFileData.cFileName, "..") != 0))
		result.push_back(FindFileData.cFileName);
 
    while(FindNextFileA(hFind, &FindFileData) != 0)
    {
		if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
			(strcmp(FindFileData.cFileName, ".") != 0) &&
			(strcmp(FindFileData.cFileName, "..") != 0))
			result.push_back(FindFileData.cFileName);
    }
 
	FindClose(hFind);

	return result;
}


}; // end namespace lidlib
